package com.aboverock.module.system.web;

import com.aboverock.autoconfigure.util.JwtUtil;
import com.aboverock.common.domain.Result;
import com.aboverock.common.enums.MessageSourceKey;
import com.aboverock.core.spring.web.StringIdBaseController;
import com.aboverock.module.shiro.service.ShiroService;
import com.aboverock.module.shiro.util.ShiroCacheUtil;
import com.aboverock.module.system.domain.Resource;
import com.aboverock.module.system.i18n.KbSmartMessageSourceKey;
import com.aboverock.module.system.service.ResourceService;
import com.aboverock.module.system.utils.UserInfoUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiOperation;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Size;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Rock Wang
 * @since 2018-04-10
 */
@RestController
@RequestMapping("system/resource")
@Validated
public class ResourceController extends StringIdBaseController<Resource> {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private final ReentrantLock operationLock = new ReentrantLock();

    @Autowired
    ResourceService resourceService;

    @Autowired
    ShiroService shiroService;

    /**
     * 获取当前用户资源.
     *
     * @return the resources
     */
    @ApiOperation(value = "获取当前用户资源")
    @GetMapping("/user")
    public Result getResources() {
        String loginName = JwtUtil.getLoginName();
        List<Resource> resources;
        if (UserInfoUtil.isSuperAdminName(loginName)) {
            resources = resourceService.list(new QueryWrapper<Resource>().orderByAsc("order_no"));
        } else {
            resources = resourceService.getResourcesByLoginName(loginName);
        }

        return Result.success(resources);
    }

    /**
     * 新建资源.
     *
     * @param resource the resource
     * @return the result
     */
    @ApiOperation(value = "新增资源")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result save(@Validated @RequestBody Resource resource) {
        operationLock.lock();
        try {
            // parent id不为空，则上级资源必须存在
            if (resource.getParentId() != null
                    && null == resourceService.getById(resource.getParentId())) {
                return Result.fail(KbSmartMessageSourceKey.PARENT_NODE_NOT_FOUND);
            }

            resource.setPermissions(resourceService.generatePermissionStr(resource));
            if (resourceService.isDuplicatedCode(resource)) {
                return Result.fail(MessageSourceKey.Common.COMMON_CODE_EXISTED);
            }
            resource.setOrderNo(System.currentTimeMillis());

            if (resourceService.save(resource)) {
                shiroService.updatePermission();
                return Result.success(resource);
            }
            return Result.fail();
        } finally {
            operationLock.unlock();
        }
    }

    /**
     * Update.
     *
     * @param resourceId the resource id
     * @param resource the resource
     * @return the result
     */
    @ApiOperation(value = "更新资源")
    @Override
    public Result update(@PathVariable("id") String resourceId,
            @Validated @RequestBody Resource resource) {
        operationLock.lock();
        try {
            Resource res = resourceService.getById(resourceId);
            if (null == res) {
                return Result.fail(MessageSourceKey.Common.COMMON_DATA_NOT_FOUND_KEY);
            }

            resource.setId(resourceId);
            resource.setPermissions(resourceService.generatePermissionStr(resource));
            if (resourceService.isDuplicatedCode(resource)) {
                return Result.fail(MessageSourceKey.Common.COMMON_CODE_EXISTED);
            }

            try {
                resourceService.update(resource, res);
                ShiroCacheUtil.getAuthorizationCache().clear();
                return Result.success(resource);
            } catch (Exception e) {
                logger.warn("Data-Smart:更新资源失败", e);
            }
            return Result.fail();
        } finally {
            operationLock.unlock();
        }
    }

    /**
     * 交换两个资源的顺序.
     *
     * @param resourceIds the resource ids
     * @return the result
     */
    @ApiOperation(value = "交换两个资源顺序")
    @PatchMapping("order/action/exchange")
    public Result exchangeOrderNo(@Size(min = 2, max = 2) @RequestBody List<Long> resourceIds) {
        operationLock.lock();
        try {
            Resource resource1 = resourceService.getById(resourceIds.get(0));
            Resource resource2 = resourceService.getById(resourceIds.get(1));
            if (null == resource1 || null == resource2) {
                return Result.fail(MessageSourceKey.Common.COMMON_DATA_NOT_FOUND_KEY);
            }

            try {
                resourceService.exchangeOrderNo(resource1, resource2);
                return Result.success();
            } catch (SQLException e) {
                logger.warn("Data-Smart:交换资源顺序失败", e);
            }
            return Result.fail();
        } finally {
            operationLock.unlock();
        }
    }

    /**
     * 删除资源及其子资源，并更新权限表.
     *
     * @param resourceId the resource id
     * @return the result
     */
    @ApiOperation(value = "删除资源")
    @Override
    public Result delete(@PathVariable("id") String resourceId) {
        operationLock.lock();
        try {
            resourceService.deleteById(resourceId);
            ShiroCacheUtil.getAuthorizationCache().clear();
            return Result.success();
        } catch (Exception e) {
            logger.warn("Data-Smart:资源删除失败", e);
        } finally {
            operationLock.unlock();
        }
        return Result.fail();
    }

    @ApiOperation(value = "获取所有接口信息")
    @GetMapping("/resturl/all")
    public Result getUrls() {
        return Result.success(resourceService.getUrls());
    }

    @Override
    @ApiOperation(value = "禁用该通用接口")
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public Result page(HttpServletRequest request) {
        return null;
    }

    @Override
    @ApiOperation(value = "禁用该通用接口")
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public Result all(HttpServletRequest request) {
        return null;
    }

    @Override
    @ApiOperation(value = "禁用该通用接口")
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public Result getById(String id) {
        return null;
    }

}
